<!doctype html>
<html>
<!-- 作者：PJ568 -->
<!-- 项目地址：https://github.com/PJ-568/markdown.html/ -->
<!-- 本项目遵循 CC BY-SA 4.0 International 许可协议 -->
<!-- v 0.6.2 -->

<head>
  <meta charset="utf-8">
  <meta name="description" content="HTML read markdown">
  <meta name="viewport" content="width=256, initial-scale=1">
  <script defer src="//lib.baomitu.com/marked/4.0.2/marked.min.js" type="text/javascript"></script>
  <script src="//lib.baomitu.com/pjax/0.2.8/pjax.min.js" type="text/javascript"></script>
  <script src="//lib.baomitu.com/translate.js/3.7.2/translate.js" type="text/javascript"></script>
  <script src="//lib.baomitu.com/Darkmode.js/1.5.7/darkmode-js.min.js" type="text/javascript"></script>
  <link rel="stylesheet" href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/font-awesome/6.0.0/css/all.min.css">
  <script>
    // 使用 IIFE 包裹以避免全局变量污染
    (function () {
      // 加载动画相关
      var loadingBar = document.querySelector('.loading-bar');
      var progress = document.querySelector('.loading-bar .progress');
      var timer = null;

      // 文档解析功能相关
      var url = new URL(window.location.href);
      var params = new URLSearchParams(url.search);
      var pValue = formatPath(params.get('p'));

      // Pjax 相关
      let pjax;

      // 自定义 PJAX 相关
      const existPushState = (history && history.pushState);

      // 初始化加载动画相关元素
      function initAni() {
        loadingBar = document.querySelector('.loading-bar');
        progress = document.querySelector('.loading-bar .progress');
      }

      // 开始加载动画
      function startLoad() {
        var loadingBarWidth = 20;
        var MAX_LOADING_WIDTH = 95;

        loadingBar.classList.add('loading');
        progress.style.width = loadingBarWidth + '%';

        clearInterval(timer);
        timer = setInterval(function () {
          loadingBarWidth += 3;

          if (loadingBarWidth > MAX_LOADING_WIDTH) {
            loadingBarWidth = MAX_LOADING_WIDTH;
          }

          progress.style.width = loadingBarWidth + '%';
        }, 500);
      }

      // 停止加载动画
      function endLoad() {
        clearInterval(timer);
        progress.style.width = '100%';
        loadingBar.classList.remove('loading');

        setTimeout(function () {
          progress.style.width = 0;
        }, 400);
      }

      // 初始化 PJAX
      function initPjax() {
        try {
          const Pjax = window.Pjax || function () { };
          pjax = new Pjax({
            selectors: [
              'head title',
              '#c',
              '.pjax-reload'
            ],
            cacheBust: false
          });
        } catch (e) {
          console.error('PJAX 初始化出错：' + e);
        }
      }

      // translate-js 翻译系统
      //// 初始化翻译系统
      function initTranslate() {
        try {
          translate.service.use('client.edge');
          translate.request.listener.start();
          translate.setAutoDiscriminateLocalLanguage();
          translate.language.setUrlParamControl();
          translate.ignore.class.push('notTranslate');
          translate.execute();
        } catch (e) {
          console.error('翻译系统出错：' + e);
        }
      }

      // 初始化返回按钮
      function initBackBtn() {
        try {
          document.querySelector('nav').addEventListener('click', function (event) {
            if (event.target.closest('#back-btn')) {
              try {
                window.history.back();
              } catch (e) {
                console.error('返回按钮出错：' + e);
              }
            }
          });
        } catch (e) {
          console.error('初始化返回按钮出错：' + e);
        }
      }

      // Darkmode.js 深色模式
      function initDarkmode() {
        try {
          const Darkmode = window.Darkmode || function () {
            console.warn('Darkmode.js 不存在？');
            return;
          };
          var darkmode = new Darkmode();
          document.querySelector('nav').addEventListener('click', function (event) {
            if (event.target.closest('#dark_b')) {
              try {
                darkmode.toggle();
              } catch (e) {
                console.error('Darkmode.js 出错：' + e);
              }
            }
          });
        } catch (e) {
          console.error('初始化 Darkmode.js 出错：' + e);
        }
      }

      //// 检查并提示翻译
      function infoTranslate() {
        try {
          var currentLang = translate.language.getCurrent();
          var originalLang = translate.language.getLocal();
          if (currentLang !== originalLang) {
            const translateInfo = document.querySelectorAll('#translate-info');
            if (translateInfo) {
              translateInfo.forEach(function (item) {
                item.remove();
              })
            }
            // 获取 #c 元素
            var mainElements = document.querySelector('#c');
            var bq = document.createElement('blockquote');
            bq.id = 'translate-info';

            var infoBody = document.createElement('p');
            infoBody.innerText = '当前页面为翻译版本。';
            var msgBody = document.createElement('p');

            var langIcon = document.createElement('i');
            langIcon.classList.add('fa');
            langIcon.classList.add('fa-language');

            var switchButton = document.createElement('a');
            switchButton.href = 'javascript:;';
            switchButton.title = '切换到原语言';
            switchButton.innerText = ' 切换到文章原本的语言';

            msgBody.appendChild(langIcon);
            msgBody.appendChild(switchButton);

            bq.appendChild(infoBody);
            bq.appendChild(msgBody);

            mainElements.insertBefore(bq, mainElements.children[1]);

            switchButton.addEventListener('click', function () {
              translate.changeLanguage(originalLang);
            });
          }
        } catch (e) {
          console.error('检查并提示翻译出错：' + e);
        }
      }

      //// 刷新翻译
      function refreshTranslate() {
        try {
          translate.selectLanguageTag.refreshRender();
        } catch (e) {
          console.error('刷新翻译出错：' + e);
        }
      }

      // 更新 p 值
      function updatePValue() {
        url = new URL(window.location.href);
        params = new URLSearchParams(url.search);
        pValue = formatPath(params.get('p'));
      }

      // 获取文件所在目录
      function getDirectory(path) {
        path = new URL(path, 'http://example.com').pathname;
        const lastSlashIndex = path.lastIndexOf('/');
        return path.substring(0, lastSlashIndex) + '/';
      }

      // 获取 markdown.html 的当前路径
      function getPath() {
        return getDirectory(window.location);
      }

      // 将 ?p= 后面的值转换为绝对路径
      function decodePath(path) {
        const url = new URL(path);
        const params = new URLSearchParams(url.search);
        return params.get('p');
      }

      // 判断路径是否为相对路径
      const isRelativePath = (path) => !path.startsWith('/');

      // 判断路径是否在本域下
      const _isSameDomain = (url) => {
        const currentDomain = window.location.origin;
        const targetDomain = new URL(url).origin;
        return currentDomain === targetDomain;
      }

      // 根据指定文件读取并解析
      const showMarkdown = async (path, response = null) => {
        try {
          if (!response) {
            response = await fetch(path);
            if (!response.ok) {
              throw new Error('请求失败');
            }
          }
          const markdown = await response.text();
          var content = marked.parse(markdown);
          content = `<blockquote><code>${decodeURIComponent(path)}</code></blockquote>${content}`;
          const parser = new DOMParser();
          const doc = parser.parseFromString(content, 'text/html');
          const links = doc.querySelectorAll('a[href$=".md"]');
          links.forEach(link => {
            var href = link.getAttribute('href');
            /* 
              如果 href 是相对路径，则在其前加上当前读取的文档的绝对路径；
              如果不存在当前读取的文档（默认读取的 index.md 或 README.md），
              则在其前加上 markdown.html 的绝对路径。
             */
            if (isRelativePath(href)) {
              if (pValue) {
                href = getDirectory(path) + href;
              } else {
                href = getPath() + href;
              }
              const absoluteHref = new URL(href, 'http://example.com').pathname;
              link.setAttribute('href', `${window.location.pathname}?p=${absoluteHref}`);
            } else if (href.startsWith('/')) {
              link.setAttribute('href', `${window.location.pathname}?p=${href}`);
            }
          });
          content = doc.body.innerHTML;
          document.getElementById('c').innerHTML = content;
          const firstH1 = document.querySelector('h1');
          document.title = firstH1 ? firstH1.textContent : path;
          showMarkdownEnded();
        } catch (error) {
          document.getElementById('c').innerHTML = `<h1>加载失败</h1><p>文档<code>${path}</code>可能不存在。您可以尝试<a href="">重试</a>。</p>`;
          console.error(error);
        }
      };

      // 格式化路径
      function formatPath(path) {
        if (path) {
          path = new URL(path, 'http://example.com').pathname;
          if (!path.endsWith('.md')) {
            path += 'index.md';
          }
        }
        return path;
      }

      // 初始化自定义 PJAX
      function initCostumedPjax() {
        if (existPushState) {
          document.querySelector('#c').addEventListener('click', function (event) {
            const link = event.target.closest('a[href$=".md"]');
            if (link) {
              try {
                event.preventDefault();
                startLoad();
                showMarkdown(decodePath(link.href));
                history.pushState({ url: link.href, title: document.title, uid: link.href }, null, link.href);
              } catch (e) {
                console.error('自定义 PJAX 出错：' + e);
              }
            }
          });
        }
      }

      // 初始化内容
      const initContent = async () => {
        try {
          if (pValue) {
            await showMarkdown(pValue);
          } else {
            const response = await fetch(getPath() + 'index.md');
            if (response.ok) {
              await showMarkdown(getPath() + 'index.md', response);
            } else {
              await showMarkdown(getPath() + 'README.md');
            }
          }
        } catch (error) {
          console.error(error);
        }
      };

      // 初始化返回首页按钮
      function initHomeBtn() {
        const homeBtn = document.getElementById('to-home');
        homeBtn.href = window.location.pathname;
      }

      // 初始化
      function initialize() {
        initDarkmode();	//// 初始化深色模式
        initBackBtn();	//// 初始化返回按钮
        initHomeBtn();	//// 初始化返回首页按钮
        initContent();	//// 初始化内容
        initTranslate();	//// 初始化页面翻译
        initPjax();	//// 初始化 Pjax
        initCostumedPjax();	//// 初始化自定义 PJAX
        initAni();	//// 初始化加载动画
        if (existPushState) {
          history.pushState({ url: window.location.href, title: document.title, uid: window.location.href }, null, window.location.href);
        }
      }

      // 触发器
      //// 网页加载完毕后触发
      window.addEventListener('DOMContentLoaded', () => initialize());
      //// 翻译执行完成后触发
      // translate.listener.renderTaskFinish = function (_task) {

      // }
      //// Pjax 开始时执行的函数
      document.addEventListener('pjax:send', function () {
        startLoad();
      });
      //// 监听 Pjax 完成后，重新加载
      document.addEventListener('pjax:complete', function () {
        updatePValue();
        initContent();
        translate.execute();    // 手动触发翻译，但是理论上 translate-js 会监听页面变化
        initCostumedPjax();	//// 初始化自定义 PJAX
      })
      //// 文档内容加载完毕时触发
      function showMarkdownEnded() {
        refreshTranslate();
        infoTranslate();	//// 检查并提示翻译
        translate.execute();    // 手动触发翻译，但是理论上 translate-js 会监听页面变化
        endLoad();
      }
    })();
  </script>
  <title>加载中</title>
  <style>
    /* 全局 */
    * {
      font-family: 'Exo', sans-serif;
      text-decoration: none;
    }

    :root {
      background-color: #e6e6e6;
    }

    ::selection {
      background-color: #DCEDC8;
    }

    body {
      margin: 0;
    }

    a {
      color: #66BB6A;
      cursor: pointer;
      text-decoration: none;
    }

    a:hover {
      color: #2E7D32;
    }

    /* 背景 */
    .background {
      position: fixed;
      left: 0;
      top: 0;
      height: 100%;
      width: 100%;
      z-index: -1;
      background-color: #e6e6e6;
    }

    /* 导航栏 */
    nav {
      position: fixed;
      top: 0;
      right: 0;
      width: min-content;
      background-color: #616161;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    nav a {
      color: #FAFAFA;
      padding: .5rem;
      transition:
        color .2s,
        background-color .2s;
    }

    nav a:hover {
      color: #FFF;
      background-color: #212121;
    }

    /* 主要内容 */
    #c {
      margin: 3rem auto;
      width: 100%;
      max-width: 950px;
      min-height: 300px;
      background-color: #FAFAFA;
      color: #212121;
      box-sizing: border-box;
      overflow-x: hidden;
      padding: 30px;
      box-shadow: 0 2px 6px rgba(100, 100, 100, .3);
    }

    #c img,
    #c video,
    #c iframe,
    #c object,
    #c embed,
    #c svg,
    #c canvas,
    #c audio {
      max-width: 100%;
    }

    /* Markdown 样式 */
    #c a {
      transition:
        color .2s,
        background-color .2s;
    }

    #c a:hover {
      background-color: rgba(255, 255, 255, 0.1);
    }

    #c pre {
      background-color: rgba(0, 0, 0, 0.05);
      padding: .4rem;
      border-radius: .5rem;
      overflow-y: scroll;
    }

    #c code {
      font-family: "cousine nerd font mono", monospace;
    }

    #c p code {
      background-color: rgba(0, 0, 0, 0.05);
      font-size: small;
      padding: .2rem;
      border-radius: .1rem;
    }

    #c blockquote {
      background-color: rgba(0, 0, 0, 0.05);
      font-size: small;
      padding: .4rem;
      border-left: 5px solid rgba(0, 0, 0, 0.1);
    }

    #c table {
      border-spacing: 0;
      border-radius: .1rem;
      width: 100%;
      border-collapse: separate;
      border: .1rem solid rgba(0, 0, 0, 0.05);
    }

    #c table td,
    #c table th {
      border-right: .1rem solid rgba(0, 0, 0, 0.05);
    }

    #c table td,
    #c table th {
      border-top: .1rem solid rgba(0, 0, 0, 0.05);
    }

    #c table td:last-child,
    #c th:last-child {
      border-right-color: transparent;
    }

    #c table thead tr:first-child>* {
      border-top: .1rem solid transparent;
    }

    /* 加载进度条 */
    .loading-bar {
      position: fixed;
      top: 0;
      left: 0;
      z-index: 99999;
      opacity: 0;
      transition: opacity .4s linear;

      .progress {
        position: fixed;
        top: 0;
        left: 0;
        width: 0;
        height: 4px;
        background-color: #FFF;
        box-shadow: 0 0 10px rgba(102, 187, 106, .7);
      }

      &.loading {
        opacity: 1;
        transition: none;

        .progress {
          transition: width .4s ease;
        }
      }
    }

    /* 翻译按钮相关 */
    .translateSelectLanguage {
      background-color: #616161;
      color: inherit;
      z-index: 10;
      width: 17%;
      height: 100%;
      opacity: 0;
      cursor: pointer;
      position: absolute;
      top: 0;
      left: 50%;
    }

    /* 深色模式相关 */
    .darkmode--activated img,
    .darkmode--activated svg {
      isolation: isolate;
      mix-blend-mode: difference
    }

    .darkmode-layer,
    .darkmode-toggle {
      z-index: 2
    }

    /* 小屏响应式优化 */
    @media only screen and (max-width: 950px) {

      html,
      body,
      #c {
        height: 100%;
      }

      #c {
        overflow-y: scroll;
        min-width: 256px;
        top: 0;
        margin: 0 0;
      }
    }
  </style>
</head>

<body>
  <!-- 导航栏 -->
  <nav>
    <a title="返回" id="back-btn"><i class="fa fa-backward"></i></a>
    <a title="刷新" href=""><i class="fa fa-arrows-rotate"></i></a>
    <a title="主页" id="to-home"><i class="fa fa-home"></i></a>
    <a title="更改语言" id="translate"><i class="fa fa-language"></i></a>
    <a title="切换显示模式" id="dark_b" href="javascript:;"><i class="fa fa-adjust"></i></a>
    <a title="关于" href="https://github.com/PJ-568/markdown.html/"><i class="fa fa-info-circle"></i></a>
  </nav>

  <!-- 内容主体 -->
  <div id="c">
    <h1>加载中……</h1>
    <p>请稍等。</p>
  </div>

  <!-- 加载动画 -->
  <div class="loading-bar">
    <div class="progress"></div>
  </div>

  <div class="background"></div>
  <script src="//lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/instant.page/5.1.0/instantpage.min.js"
    type="text/javascript"></script>
</body>

</html>